package log.controller;

import com.easyaop.api.Events;
import com.easyaop.api.event.BeforeEvent;
import com.easyaop.api.event.ReturnEvent;
import com.easyaop.api.event.ThrowableEvent;
import com.easyaop.api.listener.AbstractMethodListener;
import com.easyaop.core.EventsImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.method.support.InvocableHandlerMethod;

import java.lang.reflect.Method;

public abstract class AbstractControllerLogListener extends AbstractMethodListener {
    static final Log LOGGER = LogFactory.getLog("log.controller");

    protected abstract void log(Invocation invocation);

    @Override
    public void before(BeforeEvent event) {
        event.setData(System.currentTimeMillis());
    }

    @Override
    public void afterReturn(ReturnEvent event) {
        long startTime = (Long) event.getData();

        InvocableHandlerMethod handlerMethod = (InvocableHandlerMethod) event.getThis();
        Object[] arguments = event.getArguments();

        Object[] controllerArgs= (Object[]) arguments[0];
        Object controller = handlerMethod.getBean();
        Method controllerMethod = handlerMethod.getMethod();

        log(new Invocation(startTime,controller, controllerArgs, event.getSignature(),controllerMethod, event.getReturnValue(),null));
    }

    @Override
    public void exception(ThrowableEvent event) {
        long startTime = (Long) event.getData();

        InvocableHandlerMethod handlerMethod = (InvocableHandlerMethod) event.getThis();
        Object[] arguments = event.getArguments();

        Object[] controllerArgs= (Object[]) arguments[0];
        Object controller = handlerMethod.getBean();
        Method controllerMethod = handlerMethod.getMethod();

        log(new Invocation(startTime,controller, controllerArgs, event.getSignature(), controllerMethod,null, event.getThrowable()));    }

    public void register() {

        try {
            Events events = EventsImpl.getInstance();
            Method doInvoke = Class.forName("org.springframework.web.method.support.InvocableHandlerMethod")
                    .getDeclaredMethod("doInvoke", Object[].class);
            events.addEventListener(doInvoke, this);

        } catch (Exception e) {
            LOGGER.warn("controller invoke listener init error",e);
//            throw new RuntimeException(e);
        }
    }
}
